package cornservice

import (
	"fmt"
	"time"
	"yunj/pkg/global"
	"yunj/pkg/yunj/app/dto"
	"yunj/pkg/yunj/app/model"
	"yunj/pkg/yunj/core/builder"
	"yunj/pkg/yunj/core/builder/builderconsts"
	"yunj/pkg/yunj/core/builder/builderdto"
	"yunj/pkg/yunj/core/builder/table"
	"yunj/pkg/yunj/core/builder/table/col"
	"yunj/pkg/yunj/core/builder/table/col/action"
	"yunj/pkg/yunj/core/builder/table/deftoolbar"
	"yunj/pkg/yunj/core/builder/table/toolbar"
	"yunj/pkg/yunj/core/corn"
	"yunj/pkg/yunj/core/enum/cornenum"
	"yunj/pkg/yunj/util"

	"github.com/gin-gonic/gin"
)

type cornPage struct {
}

var CornPage *cornPage

// 列表构建器
func (s *cornPage) ListBuilder(ctx *gin.Context) *builder.Table {
	return builder.NewTable(ctx, "CornList").
		State(builder.GetEnumTableState(cornenum.TaskStatusEnum, true)).
		Toolbar(func(t *builder.Table, state *builderdto.TableState) (actions []toolbar.ActionInterface, err error) {
			actions = []toolbar.ActionInterface{}
			if state.Code == cornenum.TASK_STATUS_RUNNING {
				actions = append(actions,
					toolbar.NewAsyncEvent(cornenum.TASK_STATUS_PAUSED, "暂停").SetAuth("yunj_corn_list_paused"),
				)
			} else if state.Code == cornenum.TASK_STATUS_PAUSED {
				actions = append(actions,
					toolbar.NewAsyncEvent(cornenum.TASK_STATUS_RUNNING, "运行").SetAuth("yunj_corn_list_running"),
				)
			}
			return
		}).
		DefaultToolbar([]deftoolbar.ActionInterface{
			deftoolbar.NewFilter(),
		}).
		Pk("name").
		Page(false).
		Cols(func(t *builder.Table, state *builderdto.TableState) (cols []table.ColInterface, err error) {
			cols = []table.ColInterface{
				col.NewCheckbox("name"),
				col.NewText("name_desc", "定时任务"),
				col.NewText("desc", "描述"),
				col.NewText("corn_expression", "Corn表达式"),
				col.NewCustom("handle_errors", "近期错误").SetHtml(`<div class="item-handle-errors">{{- d.handle_errors }}</div>`).SetMinWidth(380),
				col.NewCustom("last_handle_result", "最近处理").SetHtml(`<div class="item-last-handle-result">{{- d.last_handle_result }}</div>`).SetMinWidth(380),
				col.NewText("running_time", "启动时长"),
				col.NewEnum("status", "状态").SetOptions(builder.GetEnumTableColOptions(cornenum.TaskStatusEnum)).SetAlign(builderconsts.ALIGN_CENTER).SetMaxWidth(80),
			}
			// 操作
			cols = append(cols, col.NewAction("操作").SetOptions([]action.ActionInterface{
				action.NewAsyncEvent(cornenum.TASK_STATUS_PAUSED, "暂停").SetShow(fmt.Sprintf("d.status===%d", cornenum.TASK_STATUS_RUNNING)).SetAuth("yunj_corn_list_paused"),
				action.NewAsyncEvent(cornenum.TASK_STATUS_RUNNING, "运行").SetShow(fmt.Sprintf("d.status===%d", cornenum.TASK_STATUS_PAUSED)).SetAuth("yunj_corn_list_running"),
			}))
			return
		}).
		Count(func(t *builder.Table, requestParam *builderdto.TableRequestParam) (res builderdto.TableCountResult, err error) {
			if requestParam.StateEqual(cornenum.TASK_STATUS_RUNNING) {
				for _, t := range corn.TaskScheduler.Tasks {
					if t.IsRunning() {
						res.Count++
					}
				}
			} else if requestParam.StateEqual(cornenum.TASK_STATUS_PAUSED) {
				for _, t := range corn.TaskScheduler.Tasks {
					if !t.IsRunning() {
						res.Count++
					}
				}
			} else {
				res.Count = int64(len(corn.TaskScheduler.Tasks))
			}
			return
		}).
		Items(func(t *builder.Table, requestParam *builderdto.TableRequestParam) (res builderdto.TableItemsResult, err error) {
			currTime := time.Now().In(time.Local)
			items := make([]*dto.CornPageListItemResponse, 0, len(corn.TaskScheduler.Tasks))
			for _, t := range corn.TaskScheduler.Tasks {
				if (requestParam.StateEqual(cornenum.TASK_STATUS_RUNNING) && !t.IsRunning()) || (requestParam.StateEqual(cornenum.TASK_STATUS_PAUSED) && t.IsRunning()) {
					continue
				}
				item := &dto.CornPageListItemResponse{
					Name:           t.Name(),
					NameDesc:       t.Name(),
					Desc:           t.Desc(),
					CornExpression: t.Spec(),
					Status:         t.GetHandleStatus(),
				}
				// last_handle_errors
				if handleErrors := t.GetHandleErrors(); len(handleErrors) > 0 {
					for i := len(handleErrors) - 1; i >= 0; i-- {
						handleError := handleErrors[i]
						item.HandleErrors += fmt.Sprintf(`<div style="display:inline-block;font-weight:600;padding-left:10px">%s</div>
															<div style="display:inline-block;font-weight:600;padding-left:10px">耗时：%s</div><br>
															<div style="display:inline-block;margin-left:60px;"><span style="font-weight:600;color:#31BDEC;">错误：</span>%v</div><br>`,
							handleError.Time.Format("2006-01-02 15:04:05"), util.LatencyDescByMs(handleError.Latency), handleError.Err)
					}
				}
				// last_handle_result
				if lastHandleResult := t.GetLastHandleResult(); lastHandleResult != nil {
					handleResult := cornenum.TaskHandleStatusByValue(lastHandleResult.Status)
					item.LastHandleResult = fmt.Sprintf(`<div style="display:inline-block;font-weight:600;width:50px;text-align:right;color:%s">%s</div>
														<div style="display:inline-block;font-weight:600;padding-left:10px">%s</div>
														<div style="display:inline-block;font-weight:600;padding-left:10px">耗时：%s</div><br>`,
						handleResult.GetColor(), handleResult.GetDesc(), lastHandleResult.Time.Format("2006-01-02 15:04:05"), util.LatencyDescByMs(lastHandleResult.Latency))
					if lastHandleResult.Err != nil {
						item.LastHandleResult += fmt.Sprintf(`<div style="display:inline-block;margin-left:60px;"><span style="font-weight:600;color:#31BDEC;">错误：</span>%v</div><br>`, lastHandleResult.Err)
					}
				}
				// running_time
				if t.IsRunning() {
					item.RunningTime = util.LatencyDescByMs(util.MsTimeDiff(*t.GetHandleRunAt(), currTime))
				}
				items = append(items, item)
			}
			res.Items = items
			return
		}).
		Event(func(t *builder.Table, requestParam *builderdto.TableRequestParam) (res builderdto.TableEventResult, err error) {
			for _, pk := range requestParam.Pks {
				for _, t := range corn.TaskScheduler.Tasks {
					if t.Name() == pk {
						var saveStatus uint8
						if requestParam.EventCodeEqual(cornenum.TASK_STATUS_RUNNING) {
							// 运行
							err = t.StartHandle()
							if err != nil {
								return
							}
							saveStatus = cornenum.TASK_STATUS_RUNNING
						} else if requestParam.EventCodeEqual(cornenum.TASK_STATUS_PAUSED) {
							// 暂停
							t.StopHandle()
							saveStatus = cornenum.TASK_STATUS_PAUSED
						} else {
							break
						}
						// 修改数据库状态
						item := model.Corn{
							Name:   t.Name(),
							Status: saveStatus,
						}
						err = global.MySQL.Save(&item).Error
						if err != nil {
							err = fmt.Errorf("%s修改数据库状态异常！%v", t.LogPrefix(), err)
							return
						}
					}
				}
			}
			res.Reload = true
			return
		})
}
